﻿namespace HutongGames.PlayMakerEditor
{
    using HutongGames.PlayMaker;
    using System;
    using System.Collections.Generic;
    using System.Runtime.InteropServices;
    using UnityEditor;
    using UnityEngine;

    internal class FsmSelection
    {
        private readonly Fsm activeFsm;
        private FsmState activeState;
        private FsmTransition activeTransition;
        private static readonly List<FsmSelection> Cache = new List<FsmSelection>();
        private Vector2 scrollPosition;
        private readonly List<FsmState> states = new List<FsmState>();

        private FsmSelection(Fsm fsm)
        {
            this.activeFsm = fsm;
        }

        public void AddState(FsmState state)
        {
            if (state != null)
            {
                this.activeState = state;
                if (!this.States.Contains(state))
                {
                    this.States.Add(state);
                }
                FsmEditor.StateInspector.Reset();
                FsmEditor.StateInspector.ResetScrollPosition();
                FsmEditor.ResetKeyboard();
            }
        }

        public static void ClearCache()
        {
            Cache.Clear();
        }

        public bool Contains(FsmState state)
        {
            this.SanityCheck();
            return this.States.Contains(state);
        }

        public bool Contains(FsmTransition transition)
        {
            this.SanityCheck();
            return (this.ActiveTransition == transition);
        }

        public void DeselectStates()
        {
            this.activeState = null;
            this.activeTransition = null;
            this.States.Clear();
            this.activeFsm.EditState = null;
        }

        public static Fsm FindFsm(GameObject gameObject)
        {
            foreach (Fsm fsm in FsmEditor.FsmList)
            {
                if (fsm.GameObject == gameObject)
                {
                    return fsm;
                }
            }
            return null;
        }

        public static FsmSelection GetFsmSelection(Fsm fsm)
        {
            foreach (FsmSelection selection in Cache)
            {
                if (selection.ActiveFsm == fsm)
                {
                    return selection;
                }
            }
            FsmSelection item = new FsmSelection(fsm);
            Cache.Add(item);
            item.SanityCheck();
            return item;
        }

        public void RemoveState(FsmState state)
        {
            if (state != null)
            {
                this.States.Remove(state);
                this.activeState = null;
                this.activeTransition = null;
            }
        }

        public void SanityCheck()
        {
            if (!FsmEditor.FsmContainsState(this.activeFsm, this.activeState))
            {
                this.activeState = null;
            }
            if (!FsmEditor.StateContainsTransition(this.activeState, this.activeTransition))
            {
                this.activeTransition = null;
            }
        }

        public void SelectActiveFsmGameObject()
        {
            if ((this.ActiveFsmGameObject != null) && (Selection.activeGameObject != this.ActiveFsmGameObject))
            {
                Selection.activeGameObject = this.ActiveFsmGameObject;
                EditorGUIUtility.PingObject(this.ActiveFsmGameObject);
            }
        }

        public List<FsmState> SelectAllStates()
        {
            if (this.ActiveFsm == null)
            {
                return null;
            }
            this.DeselectStates();
            foreach (FsmState state in this.ActiveFsm.States)
            {
                this.AddState(state);
            }
            return this.States;
        }

        public FsmState SelectState(FsmState state, [Optional, DefaultParameterValue(false)] bool add, [Optional, DefaultParameterValue(false)] bool subtract)
        {
            if (this.ActiveFsm == null)
            {
                return null;
            }
            if (state == null)
            {
                if (!add && !subtract)
                {
                    this.DeselectStates();
                }
                return null;
            }
            if (add)
            {
                this.AddState(state);
            }
            else if (subtract)
            {
                this.RemoveState(state);
            }
            else
            {
                if (!this.States.Contains(state))
                {
                    this.DeselectStates();
                }
                this.AddState(state);
            }
            this.activeTransition = null;
            if (!Application.isPlaying && (this.ActiveFsm != null))
            {
                this.ActiveFsm.EditState = state;
            }
            FsmEditor.Repaint(false);
            return state;
        }

        public List<FsmState> SelectStates(List<FsmState> stateSelection, [Optional, DefaultParameterValue(false)] bool add, [Optional, DefaultParameterValue(false)] bool subtract)
        {
            if (this.ActiveFsm == null)
            {
                return null;
            }
            if (!add && !subtract)
            {
                this.DeselectStates();
            }
            foreach (FsmState state in stateSelection)
            {
                if (!subtract)
                {
                    this.AddState(state);
                }
                else
                {
                    this.RemoveState(state);
                }
            }
            this.activeTransition = null;
            return this.States;
        }

        public FsmTransition SelectTransition(FsmTransition transition)
        {
            if (this.ActiveState == null)
            {
                return null;
            }
            this.activeTransition = transition;
            return transition;
        }

        public Fsm ActiveFsm
        {
            get
            {
                this.SanityCheck();
                return this.activeFsm;
            }
        }

        public GameObject ActiveFsmGameObject
        {
            get
            {
                if (this.ActiveFsm != null)
                {
                    return this.ActiveFsm.GameObject;
                }
                return null;
            }
        }

        public string ActiveFsmName
        {
            get
            {
                if (this.ActiveFsm != null)
                {
                    return this.ActiveFsm.Name;
                }
                return null;
            }
        }

        public MonoBehaviour ActiveFsmOwner
        {
            get
            {
                if (this.ActiveFsm != null)
                {
                    return this.ActiveFsm.Owner;
                }
                return null;
            }
        }

        public PrefabType ActiveFsmPrefabType
        {
            get
            {
                if (this.ActiveFsmGameObject == null)
                {
                    return PrefabType.None;
                }
                return EditorUtility.GetPrefabType(this.ActiveFsmGameObject);
            }
        }

        public FsmState ActiveState
        {
            get
            {
                this.SanityCheck();
                return this.activeState;
            }
        }

        public FsmTransition ActiveTransition
        {
            get
            {
                this.SanityCheck();
                return this.activeTransition;
            }
        }

        public int Count
        {
            get
            {
                return this.States.Count;
            }
        }

        public Vector2 ScrollPosition
        {
            get
            {
                this.SanityCheck();
                return this.scrollPosition;
            }
            set
            {
                this.scrollPosition = value;
            }
        }

        public List<FsmState> States
        {
            get
            {
                this.SanityCheck();
                return this.states;
            }
        }
    }
}

